﻿
MARSROVERS.namespace("MARSROVERS.ROVER");

/**
 * 
 * @module ROVER
 * Provides functionaly corresponding to a robotic rover
 */
MARSROVERS.ROVER = (function ($,movementsFabric,commonLibrary) {

    var movements = commonLibrary.Movements;
    
    /**
    * Constructor, creates new rovers
    * @method RoverConstructor
    * @param {Int} positionX  rover's Y coordinate 
    * @param {Int} positionY  rover's Y coordinate 
    * @param {Int} orientation  orientation of the rover, it can be North, South, East or West 
    * @return {Object} new rover object 
    */
    var RoverConstructor = function (positionX, positionY, orientation) {
        var self = this;
        self.Position = {
            X: positionX,
            Y: positionY
        };
        self.Orientation = orientation;
        self.Plateau = { X: 0, Y: 0 };
        self.movementStrategy = movementsFabric.getMovementStrategy(orientation);
        self.MovementsHistory = [];
    };

    /**
    * Sets rover's plateau
    * @method setPlateau
    * @param {Object} positionX  rover's Y coordinate 
    */
    RoverConstructor.prototype.setPlateau = function (plateau) {
        this.Plateau = plateau;
    };

    /**
    * Returns rover's orientation
    * @method getOrientation
    */
    RoverConstructor.prototype.getOrientation = function () {
        return this.Orientation;
    };

    /**
    * Moves the rover according to the instruction
    * @method move
    * @param {String} instruction  instruction to move the rover, it can be any character
    */
    RoverConstructor.prototype.move = function (instruction) {
        var charUpper = instruction.toUpperCase();
        if (validInstruction(charUpper)) {
            switch (charUpper) {
                case movements.Left:
                    this._moveLeft();
                    break;
                case movements.Right:
                    this._moveRight();
                    break;
                case movements.Forward:
                    this._moveForward();
            }
        } else {
            this.MovementsHistory.push("I do not understand that command");
        }
        return this;
    };

    /**
    * Returns rover's Y position
    * @method getYPosition
    */
    RoverConstructor.prototype.getYPosition = function() {
        return this.Position.Y;
    };

    /**
    * Returns rover's X position
    * @method getYPosition
    */
    RoverConstructor.prototype.getXPosition = function () {
        return this.Position.X;
    };
    
    /**
    * Determines if the rover can move in a given direction
    * @method canMove
    */
    RoverConstructor.prototype.canMove = function () {
        return this.movementStrategy.canMoveForward(this.Position, this.Plateau);
    };

    /**
    * Returns the last movement of the rover
    * @method getLastMovement
    */
    RoverConstructor.prototype.getLastMovement = function () {
        return this.MovementsHistory[this.MovementsHistory.length - 1];
    };
    
    //Private functions
    RoverConstructor.prototype._moveLeft = function () {
        this.Orientation = this.movementStrategy.moveLeft();
        this.MovementsHistory.push("Moving 90 degrees to the left, my new orientation is: " + this.Orientation);
        this.movementStrategy = movementsFabric.getMovementStrategy(this.Orientation);
    };

    RoverConstructor.prototype._moveRight = function () {
        this.Orientation = this.movementStrategy.moveRight();
        this.MovementsHistory.push("Moving 90 degrees to the right, my new orientation is: " + this.Orientation);
        this.movementStrategy = movementsFabric.getMovementStrategy(this.Orientation);
    };

    RoverConstructor.prototype._moveForward = function() {
        if (this.canMove()) {
            this.Position = this.movementStrategy.moveForward(this.Position);
            this.MovementsHistory.push("Moving forward to the " + this.Orientation + ", my new position is: " + this.Position.X + " " + this.Position.Y);
        }
        else {
            this.MovementsHistory.push("I can not move anymore to the " + this.Orientation);
        }
    };


    var validInstruction = function(direccion) {
        for (var movement in movements) {
            if (movements[movement] === direccion) {
                return true;
            }
        }
        return false;
    };

    return RoverConstructor;

}(jQuery, MARSROVERS.MOVEMENTFACTORY, MARSROVERS.COMMON));